home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Language/OS - Multiplatform Resource Library
/
LANGUAGE OS.iso
/
b
/
b.lha
/
B
/
src
/
bint
/
b2uni.c
< prev
next >
Wrap
C/C++ Source or Header
|
1988-11-24
|
10KB
|
390 lines
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/*
$Header: b2uni.c,v 1.4 85/08/22 16:57:24 timo Exp $
*/
#include "b.h"
#include "b0fea.h"
#include "b1obj.h"
#include "b2par.h"
#include "b2key.h"
#include "b2syn.h"
#include "b2nod.h"
#include "b3env.h"
#include "b3err.h"
#include "b3sou.h" /* for permkey() */
/* ******************************************************************** */
/* unit */
/* ******************************************************************** */
Visible bool unit_keyword() {
bool b; txptr tx0= tx;
b= how_to_keyword() || yield_keyword() || test_keyword();
tx= tx0;
return b;
}
Hidden value formlist, sharelist;
Hidden envtab reftab;
Visible literal idf_cntxt;
Forward bool is_howto_unit(), is_yield_unit(), is_test_unit();
Forward parsetree unicmd_suite(), ref_suite();
Visible parsetree unit(heading) bool heading; {
parsetree v= NilTree;
if (!heading) {
lino= 1;
cntxt= In_unit;
release(uname); uname= Vnil;
}
if (!is_howto_unit(&v, heading) &&
!is_yield_unit(&v, heading) &&
!is_test_unit(&v, heading)
)
parerr(MESS(2800, "no unit keyword where expected"));
#ifdef TYPE_CHECK
if (!heading) type_check(v);
#endif
return v;
}
/* ******************************************************************** */
/* howto_unit */
/* ******************************************************************** */
Forward value hu_formals();
Hidden bool is_howto_unit(v, heading) parsetree *v; bool heading; {
if (how_to_keyword()) {
value kw, w, f;
txptr ftx, ttx;
if (cur_ilev != 0) parerr(MESS(2801, "unit starts with indentation"));
formlist= mk_elt();
skipsp(&tx);
kw= keyword();
release(uname); uname= permkey(kw, How);
if (in(kw, kwlist)) pprerr2(kw, MESS(2802, " is a reserved keyword"));
req(":", ceol, &ftx, &ttx);
idf_cntxt= In_formal;
f= hu_formals(ftx, kw); tx= ttx;
if (!is_comment(&w)) w= Vnil;
*v= node8(HOW_TO, copy(kw), f, w, NilTree, NilTree, Vnil, Vnil);
if (!heading) {
sharelist= mk_elt();
*Branch(*v, HOW_SUITE)= unicmd_suite();
reftab= mk_elt();
*Branch(*v, HOW_REFINEMENT)= ref_suite();
*Branch(*v, HOW_R_NAMES)= reftab;
release(sharelist);
}
release(formlist);
return Yes;
}
return No;
}
Hidden value hu_formals(q, kw) txptr q; value kw; {
value t, v, w;
skipsp(&tx);
if (Text(q) && is_tag(&t)) treat_idf(t);
else t= Vnil;
skipsp(&tx);
v= Text(q) ? hu_formals(q, keyword()) : Vnil;
w= node4(FORMAL, kw, t, v);
return w;
}
/* ******************************************************************** */
/* yield_unit */
/* ******************************************************************** */
Forward parsetree ytu_formals();
Hidden bool is_yield_unit(v, heading) parsetree *v; bool heading; {
if (yield_keyword()) {
parsetree f; value name, w, adicity;
txptr ftx, ttx;
if (cur_ilev != 0) parerr(MESS(2803, "unit starts with indentation"));
formlist= mk_elt();
skipsp(&tx);
req(":", ceol, &ftx, &ttx);
f= ytu_formals(ftx, 'y', &name, &adicity); tx= ttx;
if (!is_comment(&w)) w= Vnil;
*v= node9(YIELD, copy(name), adicity, f, w, NilTree,
NilTree, Vnil, Vnil);
if (!heading) {
sharelist= mk_elt();
*Branch(*v, FPR_SUITE)= unicmd_suite();
reftab= mk_elt();
*Branch(*v, FPR_REFINEMENT)= ref_suite();
*Branch(*v, FPR_R_NAMES)= reftab;
release(sharelist);
}
release(formlist);
return Yes;
}
return No;
}
/* ******************************************************************** */
/* test_unit */
/* ******************************************************************** */
Hidden bool is_test_unit(v, heading) parsetree *v; bool heading; {
if (test_keyword()) {
parsetree f; value name, w, adicity;
txptr ftx, ttx;
if (cur_ilev != 0) parerr(MESS(2804, "unit starts with indentation"));
formlist= mk_elt();
skipsp(&tx);
req(":", ceol, &ftx, &ttx);
f= ytu_formals(ftx, 't', &name, &adicity); tx= ttx;
if (!is_comment(&w)) w= Vnil;
*v= node9(TEST, copy(name), adicity, f, w, NilTree,
NilTree, Vnil, Vnil);
if (!heading) {
sharelist= mk_elt();
*Branch(*v, FPR_SUITE)= unicmd_suite();
reftab= mk_elt();
*Branch(*v, FPR_REFINEMENT)= ref_suite();
*Branch(*v, FPR_R_NAMES)= reftab;
release(sharelist);
}
release(formlist);
return Yes;
}
return No;
}
/* ******************************************************************** */
#define FML_IN_FML MESS(2805, " is already a formal parameter or operand")
#define SH_IN_FML MESS(2806, " is already a formal parameter")
#define SH_IN_SH MESS(2807, " is already a shared identifier")
#define REF_IN_FML MESS(2808, " is already a formal parameter")
#define REF_IN_SH MESS(2809, " is already a shared identifier")
#define REF_IN_REF MESS(2810, " is already a refinement name")
Hidden Procedure treat_idf(t) value t; {
switch (idf_cntxt) {
case In_formal: if (in(t, formlist)) pprerr2(t, FML_IN_FML);
insert(t, &formlist);
break;
case In_share: if (in(t, formlist)) pprerr2(t, SH_IN_FML);
if (in(t, sharelist)) pprerr2(t, SH_IN_SH);
insert(t, &sharelist);
break;
case In_ref: if (in(t, formlist)) pprerr2(t, REF_IN_FML);
if (in(t, sharelist)) pprerr2(t, REF_IN_SH);
break;
case In_ranger: break;
default: break;
}
}
Forward parsetree fml_operand();
Hidden parsetree ytu_formals(q, yt, name, adic)
txptr q; char yt; value *name, *adic; {
parsetree v1, v2, v3;
*name= Vnil;
idf_cntxt= In_formal;
v1= fml_operand(q);
skipsp(&tx);
if (!Text(q)) { /* zeroadic */
*adic= zero;
if (nodetype(v1) == TAG) {
*name= *Branch(v1, TAG_NAME);
release(uname); uname= permkey(*name, Zer);
} else
pprerr(MESS(2811, "user defined functions must be tags"));
return v1;
}
v2= fml_operand(q);
skipsp(&tx);
if (!Text(q)) { /* monadic */
*adic= one;
if (nodetype(v1) == TAG) {
*name= *Branch(v1, TAG_NAME);
release(uname); uname= permkey(*name, Mon);
} else
pprerr(MESS(2812, "no monadic function name"));
if (nodetype(v2) == TAG) treat_idf(*Branch(v2, TAG_NAME));
return node4(yt == 'y' ? MONF : MONPRD, *name, v2, Vnil);
}
v3= fml_operand(q);
/* dyadic */
*adic= mk_integer(2);
if (nodetype(v2) == TAG) {
*name= *Branch(v2, TAG_NAME);
release(uname); uname= permkey(*name, Dya);
} else
pprerr(MESS(2813, "no dyadic function name"));
upto(q, "dyadic formal formula");
if (nodetype(v1) == TAG) treat_idf(*Branch(v1, TAG_NAME));
if (nodetype(v3) == TAG) treat_idf(*Branch(v3, TAG_NAME));
return node5(yt == 'y' ? DYAF : DYAPRD, v1, *name, v3, Vnil);
}
Hidden parsetree fml_operand(q) txptr q; {
value t;
skipsp(&tx);
if (nothing(q, "formal operand")) return NilTree;
else if (is_tag(&t)) return node2(TAG, t);
else if (open_sign()) return compound(q, idf);
else {
parerr(MESS(2814, "no formal operand where expected"));
tx= q;
return NilTree;
}
}
/* ******************************************************************** */
/* unit_command_suite */
/* ******************************************************************** */
Forward parsetree ucmd_seq();
Forward bool share();
Hidden parsetree unicmd_suite() {
if (ateol())
return ucmd_seq(0, Yes);
else {
parsetree v; value c; intlet l= lino;
suite_command(&v, &c);
return node5(SUITE, mk_integer(l), v, c, NilTree);
}
}
Hidden parsetree ucmd_seq(cil, first) intlet cil; bool first; {
value c; intlet level, l;
level= ilev(); l= lino;
if (is_comment(&c))
return node5(SUITE, mk_integer(l), NilTree, c,
ucmd_seq(cil, first));
if ((level == cil && !first) || (level > cil && first)) {
parsetree v;
findceol();
if (share(ceol, &v, &c))
return node5(SUITE, mk_integer(l), v, c,
ucmd_seq(level, No));
veli();
return cmd_suite(cil, first);
}
veli();
return NilTree;
}
Hidden bool share(q, v, c) txptr q; parsetree *v; value *c; {
if (share_keyword()) {
idf_cntxt= In_share;
*v= node2(SHARE, idf(q));
*c= tail_line();
return Yes;
}
return No;
}
/* ******************************************************************** */
/* refinement_suite */
/* ******************************************************************** */
Hidden parsetree ref_suite() {
value name; bool t;
if (ilev() > 0) {
parerr(MESS(2815, "indentation where not allowed"));
return NilTree;
}
if ((t= is_tag(&name)) || is_keyword(&name)) {
parsetree v, s; value w, *aa, r;
skipsp(&tx);
if (Char(tx) != ':') {
release(name);
tx= fcol();
veli(); return NilTree;
}
/* lino= 1; cntxt= In_ref; */
tx++;
if (t) {
idf_cntxt= In_ref;
treat_idf(name);
}
if (in_env(reftab, name, &aa)) pprerr2(name, REF_IN_REF);
findceol();
if (!is_comment(&w)) w= Vnil;
s= cmd_suite(0, Yes);
v= node6(REFINEMENT, name, w, s, Vnil, Vnil);
e_replace(r= mk_ref(v), &reftab, name);
release(r);
*Branch(v, REF_NEXT)= ref_suite();
return v;
}
veli();
return NilTree;
}
/* ******************************************************************** */
/* collateral, compound */
/* ******************************************************************** */
Hidden parsetree n_collateral(q, n, base)
txptr q; intlet n; parsetree (*base)(); {
parsetree v, w; txptr ftx, ttx;
if (find(",", q, &ftx, &ttx)) {
w= (*base)(ftx); tx= ttx;
v= n_collateral(q, n+1, base);
} else {
w= (*base)(q);
if (n == 1) return w;
v= mk_compound(n);
}
*Field(v, n-1)= w;
return n > 1 ? v : node2(COLLATERAL, v);
}
Visible parsetree collateral(q, base) txptr q; parsetree (*base)(); {
return n_collateral(q, 1, base);
}
Visible parsetree compound(q, base) txptr q; parsetree (*base)(); {
parsetree v; txptr ftx, ttx;
req(")", q, &ftx, &ttx);
v= (*base)(ftx); tx= ttx;
return node2(COMPOUND, v);
}
/* ******************************************************************** */
/* idf, singidf */
/* ******************************************************************** */
Hidden parsetree singidf(q) txptr q; {
parsetree v;
skipsp(&tx);
if (nothing(q, "identifier"))
v= NilTree;
else if (open_sign())
v= compound(q, idf);
else if (is_tag(&v)) {
treat_idf(v);
v= node2(TAG, v);
} else {
parerr(MESS(2816, "no identifier where expected"));
v= NilTree;
}
upto(q, "identifier");
return v;
}
Visible parsetree idf(q) txptr q; {
return collateral(q, singidf);
}